﻿
using System;

namespace My.Ioc.Condition
{
    public interface IInjectionCondition
    {
        bool Match(IInjectionInfo info);
    }

    class ParentTypesInjectionCondition : IInjectionCondition
    {
        readonly Type[] _parentTypes;

        public ParentTypesInjectionCondition(Type[] parentTypes)
        {
            _parentTypes = parentTypes;
        }

        #region IConditionEvaluator Members

        public bool Match(IInjectionInfo info)
        {
            if (info == null)
                return false;
            var parentType = info.SiteType;
            foreach (var type in _parentTypes)
            {
                if (type == parentType)
                    return true;
            }
            return false;
        }

        #endregion
    }
    class ParentTypeInjectionCondition : IInjectionCondition
    {
        readonly Type _parentType;

        public ParentTypeInjectionCondition(Type parentType)
        {
            _parentType = parentType;
        }

        #region IConditionEvaluator Members

        public bool Match(IInjectionInfo info)
        {
            return info != null && _parentType == info.SiteType;
        }

        #endregion
    }
    class TargetAttributeInjectionCondition : IInjectionCondition
    {
        readonly Type _targetAttribType;

        public TargetAttributeInjectionCondition(Type targetAttribType)
        {
            _targetAttribType = targetAttribType;
        }

        #region IConditionEvaluator Members

        public bool Match(IInjectionInfo info)
        {
            return info != null && info.TargetAttributeProvider.IsDefined(_targetAttribType, false);
        }

        #endregion
    }
    class TargetNameInjectionCondition : IInjectionCondition
    {
        readonly string _targetName;

        public TargetNameInjectionCondition(string targetName)
        {
            _targetName = targetName;
        }

        #region IConditionEvaluator Members

        public bool Match(IInjectionInfo info)
        {
            return info != null && info.TargetName == _targetName;
        }

        #endregion
    }
    class NoParentInjectionCondition : IInjectionCondition
    {
        #region IConditionEvaluator Members

        public bool Match(IInjectionInfo info)
        {
            return info == null;
        }

        #endregion
    }
    class ParentMetadataInjectionCondition : IInjectionCondition
    {
        readonly Predicate<object> _metadataCondition;

        public ParentMetadataInjectionCondition(Predicate<object> metadataCondition)
        {
            _metadataCondition = metadataCondition;
        }

        #region IConditionEvaluator Members

        public bool Match(IInjectionInfo info)
        {
            return info != null && _metadataCondition.Invoke(info.SiteMetadata);
        }

        #endregion
    }
    class PredicateInjectionCondition : IInjectionCondition
    {
        readonly Predicate<IInjectionInfo> _condition;

        public PredicateInjectionCondition(Predicate<IInjectionInfo> condition)
        {
            _condition = condition;
        }

        #region IConditionEvaluator Members

        public bool Match(IInjectionInfo info)
        {
            return info != null && _condition.Invoke(info);
        }

        #endregion
    }
}